package com.pillpoppers.pillbox.contentprovider;

import java.util.Arrays;
import java.util.HashSet;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import com.pillpoppers.pillbox.database.PillDatabaseHelper;
import com.pillpoppers.pillbox.database.PillTable;


public class PillContentProvider extends ContentProvider 
{
  // establish the database
  private PillDatabaseHelper database;

  // ints used int or the UriMatcher
  private static final int PILLS = 10;
  private static final int PILL_ID = 20;
  private static final String AUTHORITY = "com.pillpoppers.pillbox.contentprovider";
  private static final String BASE_PATH = "pills";
  private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  
  public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
  public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/pills";
  public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/pill";

  static
  {
	  sURIMatcher.addURI(AUTHORITY, BASE_PATH, PILLS);
	  sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", PILL_ID);
  }

  // Creation
  @Override
  public boolean onCreate()
  {
	  database = new PillDatabaseHelper(getContext());
	  return false;
  }

  // Cursor for query
  @Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
  {
	  // Using SQLiteQueryBuilder instead of query() method
	  SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

	  // Checks for existing column.
	  checkColumns(projection);

	  // Establish the table
	  queryBuilder.setTables(PillTable.TABLE_PILL);

	  int uriType = sURIMatcher.match(uri);
	  
	  switch (uriType)
	  {
	  	case PILLS:
	  		// None for now.
	  		break;
	  		
	  	case PILL_ID:
	  		
	  		// adds this ID to original query
	  		queryBuilder.appendWhere(PillTable.COLUMN_ID + "=" + uri.getLastPathSegment());
	  		break;
	  		
	  	default:
	  		// Throws exception when not found.
	  		throw new IllegalArgumentException("Unknown URI: " + uri);
	  }

	  SQLiteDatabase db = database.getWritableDatabase();
	  
	  Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
	  
	  // Notifies listeners
	  cursor.setNotificationUri(getContext().getContentResolver(), uri);

	  return cursor;
  }

  @Override
  public String getType(Uri uri)
  {
	  return null;
  }
  
  // Inserting into the database.
  @Override
  public Uri insert(Uri uri, ContentValues values)
  {
	  int uriType = sURIMatcher.match(uri);
	  SQLiteDatabase sqlDB = database.getWritableDatabase();
	  long id = 0;
    
	  switch (uriType)
	  {
	  	// Sets up for insertion
    	case PILLS:
    		id = sqlDB.insert(PillTable.TABLE_PILL, null, values);
    		break;
    		
    	default:
    		// If uri not found, throws exception.
    		throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    
    getContext().getContentResolver().notifyChange(uri, null);
    return Uri.parse(BASE_PATH + "/" + id);
  }

  // Deletion form database.
  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs)
  {
	  int uriType = sURIMatcher.match(uri);
	  SQLiteDatabase sqlDB = database.getWritableDatabase();
	  int rowsDeleted = 0;
    
	  switch (uriType)
	  {
	  		case PILLS:
	  			rowsDeleted = sqlDB.delete(PillTable.TABLE_PILL, selection, selectionArgs);
	  			break;
	  			
	  		case PILL_ID:
	  			String id = uri.getLastPathSegment();
	  			
	  			if(TextUtils.isEmpty(selection))
	  			{
	  				rowsDeleted = sqlDB.delete(PillTable.TABLE_PILL, PillTable.COLUMN_ID + "=" + id, null);
	  			}
	  			else
	  			{
	  				rowsDeleted = sqlDB.delete(PillTable.TABLE_PILL, PillTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
	  			}
	  			break;
	  		
	  		default:
	  			// If Uri not found throw exception.
	  			throw new IllegalArgumentException("Unknown URI: " + uri);
	  }
	  
	  getContext().getContentResolver().notifyChange(uri, null);
	  return rowsDeleted;
  }
  
  // When table is updated/edited.
  @Override
  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
  {
	  SQLiteDatabase sqlDB = database.getWritableDatabase();
	  int rowsUpdated = 0;
      int uriType = sURIMatcher.match(uri);
	  
	  switch (uriType)
	  {
	  		case PILLS:
	  			rowsUpdated = sqlDB.update(PillTable.TABLE_PILL, values, selection, selectionArgs);
	  			break;
	  			
	  		case PILL_ID:
	  			String id = uri.getLastPathSegment();
	  			if(TextUtils.isEmpty(selection))
	  			{
	  				rowsUpdated = sqlDB.update(PillTable.TABLE_PILL, values, PillTable.COLUMN_ID + "=" + id, null);
	  			}
	  			else
	  			{
	  				rowsUpdated = sqlDB.update(PillTable.TABLE_PILL, values, PillTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
	  			}
	  			break;
	  			
	  		default:
	  			// If Uri not found, then throw exception.
	  			throw new IllegalArgumentException("Unknown URI: " + uri);
	  }
	  
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
  }

  // Method checks to see if column exists.
  private void checkColumns(String[] projection)
  {
	  String[] available = { PillTable.COLUMN_TYPE, PillTable.COLUMN_NAME, PillTable.COLUMN_DESCRIPTION,
			  				PillTable.COLUMN_CURRENT_COUNT, PillTable.COLUMN_MAX_COUNT, PillTable.COLUMN_WARNINGS,
			  				PillTable.COLUMN_SIDE_EFFECTS, PillTable.COLUMN_CONTACT, PillTable.COLUMN_ID };
    
	  if (projection != null)
	  {
		  HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
		  HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
      
		  // Checks if requested columns are available.
		  if (!availableColumns.containsAll(requestedColumns))
		  {
			  throw new IllegalArgumentException("Unknown columns in projection");
		  }
	  }
  }
}